/**
 * 
 */
package forum;

import java.text.SimpleDateFormat;

import java.util.ArrayList;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;

import utils.LogHelper;

/**
 * @author Olga
 * 
 */
public class Post {

	private int ID;
	private String subject;
	private String content;
	private String date;
	private Post parent;
	private List<Post> replies;
	private String author;

	/**
	 * 
	 * @param id
	 *            - unique id of the post
	 * @param subject
	 * @param content
	 * @param parent
	 *            - in case of root post, parent is null.
	 * @param author
	 *            - username of poster
	 */
	public Post(int id, String subject, String content, Post parent, String date,
			String author) {
		this.ID = id;
		this.subject = subject;
		this.content = content;
		Date tmp = GregorianCalendar.getInstance().getTime();
		SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH-mm-ss");
		this.date = format.format(tmp); 
		this.parent = parent;
		this.replies = new ArrayList<Post>();
		this.author = author;
		this.date = date;
	}

	/**
	 * updates content of post and date to current date.
	 * 
	 * @param content
	 *            - new content of the post
	 * @return true on success. false if such post with such author, subject and
	 *         content is already exists
	 */
	public synchronized boolean editPost(String content) {
		if (!this.isExistBrother(content)) {
			this.setContent(content);
			Date tmp = GregorianCalendar.getInstance().getTime();
			SimpleDateFormat format = new SimpleDateFormat("dd.MM.yyyy HH-mm-ss");
			this.date = format.format(tmp); 
			LogHelper.instance()
					.log("Post with id " + this.ID + " edited with: "
							+ this.content);
			return true;
		} else
			LogHelper
					.instance()
					.log("Cannot edit post with id "
							+ this.ID
							+ ". Post with such subject, author and content is already exist.");
		return false;
	}

	/**
	 * 
	 * @param content
	 *            - new content
	 * @return true if post with such subject and content is exist within
	 *         brothers of this post
	 */
	private synchronized boolean isExistBrother(String content) {
		// this is root post. It has no brothers
		if (this.parent == null)
			return false;
		for (Post p : this.parent.getReplies()) {
			if (p != this && p.getAuthor().equalsIgnoreCase(this.author)
					&& p.getSubject().equalsIgnoreCase(this.subject)
					&& p.getContent().equalsIgnoreCase(content))
				return true;
		}
		return false;
	}

	/**
	 * @param reply
	 * @return true on success, false if this reply is already exist
	 */
	public synchronized boolean addReply(Post reply) {
		if (!this.isExists(reply.getAuthor(), reply.getSubject(),
				reply.getContent())) {
			reply.setParent(this);
			LogHelper.instance().log(
					"Adding post reply with id: " + reply.getID());
			return this.replies.add(reply);
		} else {
			LogHelper.instance().log(
					"Reply from user " + reply.getAuthor() + " to post "
							+ this.getID() + " with subject "
							+ reply.getSubject() + " was already added!");
			return false;
		}
	}

	/**
	 * 
	 * @param author
	 * @param subject
	 * @param content
	 * @return true if the reply post with author, subject and content is
	 *         already exists, return false otherwise
	 */
	private synchronized boolean isExists(String author, String subject,
			String content) {
		for (Post p : this.replies) {
			if (p.getAuthor().equalsIgnoreCase(author)
					&& p.getSubject().equalsIgnoreCase(subject)
					&& p.getContent().equalsIgnoreCase(content))
				return true;
		}
		return false;
	}

	/**
	 * 
	 * @param postID
	 *            - ID of post to search for
	 * @return Post with postID if found. Otherwise returns null
	 */

	public synchronized Post findPost(int postID) {
		Post ans = null;
		if (postID == this.ID) {
			LogHelper.instance().log("Finded post with id: " + postID);
			return this;
		}
		for (Post p : this.replies) {
			ans = p.findPost(postID);
			if (ans != null) {
				LogHelper.instance().log("Finded post with id: " + postID);
				return ans;
			}
		}
		return ans;
	}

	/**
	 * @return the iD
	 */
	public synchronized int getID() {
		return ID;
	}

	/**
	 * @param parent
	 *            the parent to set
	 */
	public synchronized void setParent(Post parent) {
		this.parent = parent;
	}

	/**
	 * @return the subject
	 */
	public synchronized String getSubject() {
		return subject;
	}

	/**
	 * @return the content
	 */
	public synchronized String getContent() {
		return content;
	}

	/**
	 * @param content
	 *            the content to set
	 */
	public synchronized void setContent(String content) {
		this.content = content;
	}

	/**
	 * @return the date
	 */
	public synchronized String getDate() {
		return date;
	}

	/**
	 * @param date
	 *            the date to set
	 */
	public synchronized void setDate(String date) {
		this.date = date;
	}

	/**
	 * @return the parent
	 */
	public synchronized Post getParent() {
		return parent;
	}

	/**
	 * @return the replies
	 */
	public synchronized List<Post> getReplies() {
		return replies;
	}

	/**
	 * @return the author
	 */
	public synchronized String getAuthor() {
		return author;
	}

	/**
	 * 
	 * @return only the content of the post node the structure: <br>
	 *         <xmp>PostNode <PostID>\n<author>\n<date>\n<parentID>\n
	 *         <subject>\n<content></xmp>
	 */
	public synchronized String showSinglePost() {
		String ans = "PostNode:\n";
		ans += this.ID + "\n";
		ans += this.author + "\n";
		ans += this.getDate().toString() + "\n";
		if (this.parent != null)
			ans += this.parent.getID() + "\n";
		else
			ans += -1 + "\n";
		ans += this.subject + "\n";
		ans += this.content + "\n";
		return ans;
	}

	/**
	 * 
	 * @return only the content of the post replies
	 */
	public synchronized String showPostReplies() {
		String ans = "";
		for (Post p : this.replies) {
			ans += p.showSinglePost();
		}
		return ans;
	}

	/**
	 * 
	 * @return only post and the replies to it
	 */
	public synchronized String showPostWithReplies() {
		String ans = "";
		ans += this.showSinglePost();
		ans += this.showPostReplies();
		return ans;
	}

	/**
	 * 
	 * @return all the tree of posts that are replies to current
	 */
	public synchronized String showPostTree() {
		String ans = "";
		ans += this.showSinglePost();
		for (Post p : this.replies) {
			ans += p.showPostTree();
		}
		return ans;
	}

        /**
         * Attention! Must be called only from GUI!!!
         * @return only subject of post!!!
         */
    @Override
       public String toString(){
                return this.subject;
       }

	/**
	 * 
	 * @param reply
	 *            - reply to remove
	 * @return
	 */
	public synchronized boolean removeReply(Post reply) {
		LogHelper.instance().log("Removing post with id: " + reply.getID());
		return this.replies.remove(reply);
	}
}
